use std::io::{Result};
use std::fmt;
use super::cpblock::CPBlock;
use super::head::Headed;

pub struct Addon<T> where T:Addons+Headed {
    pub block: CPBlock<T>,
    pub addon: T
}

impl<T:Addons+Headed> Addon<T> {
    pub fn attach(fname: String) -> Result<Self> {
        let cpb = CPBlock::<T>::attach(fname)?;
        let aon = T::init(&cpb)?;
        Ok(Addon::<T>{block: cpb, addon:aon})
    }    
}


// example
#[derive(Debug)]
pub struct NilAddon{}

pub trait Addons {
    fn init<T: Headed>(s:&CPBlock<T>) -> Result<Self> where Self: Sized;
}

pub type CPBuffer = Addon<NilAddon>;

impl fmt::Display for Addon<NilAddon> { 
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"{}",self.block)
    }
}

impl Headed for NilAddon {
    type ehead = Self;
}

impl Addons for NilAddon {
    fn init<T: Headed>(_cpb: &CPBlock<T>) -> Result<NilAddon> { Ok(NilAddon{}) }
}

